<script lang="jsx">
  import { TYPE_ADD, TYPE_PREVIEW, TYPE_EDIT, REQ_METHOD } from '../token.js'
  import { formatData, mergeVModel, isEmptyObj, combineUrl } from '../utils.js'

  export default {
    name: 'CrudTableDialog',
    props: {
      debug: Boolean,
      formProps: {
        type: Object,
        default: () => ({})
      },
      defaultFields: {
        type: Object,
        default: () => ({})
      },
      inFormatter: [Object, Function],
      outFormatter: [Object, Function]
    },
    data() {
      return {
        visible: false,
        form: {},
        title: '',
        type: '',
        loadData: false,
        isConfirm: false,
        isQuery: false,
        reqUrl: '',
        reqBody: {}
      }
    },
    inject: ['getTableDatas'],
    methods: {
      async open({ type, title, url, echoUrl, extraData = {}, isQuery = false, reqEntity}) {
        this.form = Object.assign({}, this.defaultFields)
        if(url !== undefined) this.reqUrl = url
        this.reqBody = { ...reqEntity }
        this.title = title
        this.type = type
        this.isQuery = isQuery
        if(!isEmptyObj(extraData)) {
          this.form = formatData(extraData, this.inFormatter)
        }
        this.visible = true
        this.$emit('dialogChange', { open: true, type })
        if(echoUrl && type !== TYPE_ADD) { // 查看和编辑获取新数据
          await this.setRefreshData(echoUrl, extraData.id)
        }
      },
      async setRefreshData(echoUrl, id) {
        this.loadData = true
        try {
          const { data:freshData } = await this.$_request({
            url: this.isQuery ? echoUrl + '?id=' + id : combineUrl(echoUrl, id),
            method: 'get'
          })
          this.form = formatData(freshData, this.inFormatter)
          return Promise.resolve()
        } catch (e) {
          console.log(e)
        } finally {
          this.loadData = false
        }
      },
      setDialogField(fieldName, value) {
        this.form[fieldName] = value
      },
      onDialogClosed() {
        this.visible = false
        this.$refs.formRef.resetFields()
        for (const key in this.form) {
          this.form[key] = undefined
          delete this.form[key]
        }
        this.$emit('dialogChange', { open: false, type: this.type })
      },
      onDialogConfirm() {
        this.$refs.formRef.validate(async (valid) => {
          if(valid) {
            this.isConfirm = true
            const type = this.type
            try {
              const data = formatData(this.form, this.outFormatter)
              const reqEntity = {
                url: this.reqUrl,
                method: REQ_METHOD[type],
                data,
                ...this.reqBody
              }
              if(this.debug) {
                console.log(reqEntity)
                return
              }
              const res = await this.$_request(reqEntity)
              if(type === TYPE_ADD) {
                this.$message({message: res.msg || res.message || '新增成功', type: 'success'})
                this.getTableDatas(true)
              }
              if(type === TYPE_EDIT) {
                this.$message({message: res.msg || res.message ||  '修改成功', type: 'success'})
                this.getTableDatas(false)
              }
              this.$emit('successed', { type, res, form: data })
              this.visible = false
              this.reqUrl = null
            } catch (e) {
              console.log(e)
            } finally {
              this.isConfirm = false
            }
          }
        })
      },
      getFooterNodes() {
        if(this.type === TYPE_PREVIEW) {
          return (
            <el-button onClick={()=>{this.visible = false}} type="primary">确定</el-button>
          )
        }
        return (
          <div>
            <el-button onClick={()=>{this.visible = false}} type="default">取消</el-button>
            <el-button onClick={this.onDialogConfirm} loading={this.isConfirm} type="primary">确定</el-button>
          </div>
        )
      }
    },
    render() {
      const { formDialog: formDialogSlots, default: defaultSlots } = this.$scopedSlots
      const formNodes = formDialogSlots && mergeVModel(formDialogSlots({form: this.form}), this.form, this.type === TYPE_PREVIEW)

      return (
        <el-dialog
          title={this.title}
          visible={ this.visible }
          on-closed={ this.onDialogClosed }
          append-to-body
          props={this.$attrs}
          close-on-click-modal={false}
          {...{on:{close: () => this.visible = false}}}
        >
          <el-form
            ref="formRef"
            v-loading={this.loadData}
            key={this.type}
            inline
            label-position="left"
            label-width="110px"
            props={{model: this.form, ...this.formProps}}
          >
          { formNodes }
          </el-form>
          <div slot="footer" class="crud-table-dialog-footer">
          { this.getFooterNodes() }
          </div>
        </el-dialog>
      )
    }
  }
</script>

